/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package technotheist.imgcog.net;

import technotheist.imgcog.base.Module;

/**
 *
 * @author Mitch
 */
public abstract class Net extends Module{


    @Override
    protected NetRunner runner() {
        return (NetRunner) super.runner();
    }

    protected void setMode(int m) {
        runner().Mode[0] = m;
        runner().put(runner().Mode);
    }

    protected abstract class NetRunner extends Runner {

//        static final byte BIPOLAR = 0x1;
//        static final byte SIGMOID = 0x2;
//        static final byte STEP = 0x4;
//        static final byte SHARED_BIAS = 0x8;
//        static final byte SHARED_WEIGHT = 0x10;
//        static final byte MULT_INPUTS = 0x20;
        //
        //
        //
        protected final int[] Mode = new int[1];
        //
        protected final int nodeCountTotal;
        private final float[] nodes_even;
        private final float[] nodes_odd;
        protected final int weightCountTotal;
        private final float[] weights;
        //
        private final float[] bias;
        //

        protected NetRunner(int inSize, int outSize, int nodes_even, int nodes_odd, int weights, int bias) {
            super(inSize, outSize);
            //
            nodeCountTotal = nodes_even + nodes_odd;
            weightCountTotal = weights;
            this.nodes_even = new float[nodes_even];
            this.nodes_odd = new float[nodes_odd];
            this.weights = new float[weights];
            this.bias = new float[bias];
        }

        protected NetRunner(NetConfig config) {
            super(config);
            //
            //Initialize nodes
            nodes_even = new float[config.getNodesEvenCount()];
            nodes_odd = new float[config.getNodesOddCount()];
            nodeCountTotal = config.getNodesCountTotal();
            weightCountTotal = config.getWeightCountTotal();
            weights = new float[weightCountTotal];
            int w0 = 0;
            //
            //Initialise bias
            if (config.hasSharedBias()) {
                bias = new float[config.getLayerCount()];
            } else {
                bias = new float[nodeCountTotal];
            }
            setExplicit(true);
        }
        
        
        //
        //
        protected float get_node_even(int index) {
            return nodes_even[index];
        }

        protected float get_node_odd(int index) {
            return nodes_odd[index];
        }

        protected float get_weight(int index) {
            return weights[index];
        }

        protected float get_bias(int index) {
            return bias[index];
        }
        
        protected void set_node_even(int index, float val) {
            nodes_even[index] = val;
        }

        protected void set_node_odd(int index, float val) {
            nodes_odd[index] = val;
        }

        protected void set_weight(int index, float val) {
            weights[index] = val;
        }

        protected void set_bias(int index, float val) {
            bias[index] = val;
        }
        

        

        public abstract float f(float x);
        public abstract float df(float fx);

        /*
         * Getters and Setters
         */
        protected int getInputSize() {
            return layer0Size;
        }

        protected int getOutputSize() {
            return layerNSize;
        }

        protected int getNodeCountTotal() {
            return nodeCountTotal;
        }

        protected int getWeightCountTotal() {
            return weightCountTotal;
        }

        /*
         * 
         */
        //Math functions
//        protected float func(float x, byte flag) {
//            if ((flag & SIGMOID) == SIGMOID) {
//                if ((flag & BIPOLAR) == BIPOLAR) {
//                    return biSigFunc(x);
//                } else {
//                    return uniSigFunc(x);
//                }
//            } else {
//                if ((flag & BIPOLAR) == BIPOLAR) {
//                    return biLinFunc(x);
//                } else {
//                    return uniLinFunc(x);
//                }
//            }
//        }
//
//        protected float deriv(float x, byte flag) {
//            if ((flag & SIGMOID) == SIGMOID) {
//                if ((flag & BIPOLAR) == BIPOLAR) {
//                    return biSigDeriv(x);
//                } else {
//                    return uniSigDeriv(x);
//                }
//            } else {
//                return 1f;
//            }
//        }
    }
}
